package other.edan.pass.utils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.rkhd.platform.sdk.data.model.Order;
import com.rkhd.platform.sdk.exception.ScriptBusinessException;
import com.rkhd.platform.sdk.exception.XsyHttpException;
import com.rkhd.platform.sdk.http.RkhdHttpClient;
import com.rkhd.platform.sdk.http.RkhdHttpData;
import com.rkhd.platform.sdk.log.Logger;
import com.rkhd.platform.sdk.log.LoggerFactory;
import org.apache.commons.lang.StringUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ComUtils {
    private static final Logger logger = LoggerFactory.getLogger();

    public static void main(String[] args) throws Exception {
        JSONArray globalPick37__c = getGlobalPicks("globalPick37__c");
        System.err.println(globalPick37__c.toJSONString());

        Integer a004 = getValueByApiKey(globalPick37__c, "A004");
        System.err.println(a004);
    }

    /**
     * 获取实体的描述(新接口)
     *
     * @param entityName
     * @return
     * @throws Exception
     */
    @SuppressWarnings("deprecation")
    public static JSONObject getEntityDesc(String entityName) throws Exception {
        RkhdHttpData data = new RkhdHttpData();
        data.setCall_type("GET");
        data.setCallString("/rest/data/v2.0/xobjects/" + entityName + "/description");
        String res = RkhdHttpClient.instance().performRequest(data);
        return JSONObject.parseObject(res);
    }


    /**
     * 根据单选框的value(数值) 获取单选框的label(中文)值
     *
     * @param resJ
     * @param fieldName
     * @param optionCode
     * @return
     */
    public static String getComboboxLabel(JSONObject resJ, String fieldName, Integer optionCode) {
        if (optionCode == null) {
            return null;
        }
        Map<String, String> map = getMapsFromDescribeJson(resJ, fieldName, "label", "value");
        for (Map.Entry<String, String> index : map.entrySet()) {
            if (optionCode.toString().equals(index.getValue())) {
                return index.getKey();
            }
        }
        return null;
    }

    /**
     * 根据单选框的label获取单选框的value值
     *
     * @param resJ
     * @param fieldName
     * @param label
     * @return
     */
    public static Integer getComboboxValue(JSONObject resJ, String fieldName, String label) {
        if (StringUtils.isBlank(label)) {
            return null;
        }
        Integer optionValue = null;
        Map<String, String> map = getMapsFromDescribeJson(resJ, fieldName, "label", "value");
        for (Map.Entry<String, String> index : map.entrySet()) {
            if (label.equals(index.getKey())) {
                optionValue = Integer.valueOf(index.getValue());
                break;
            }
        }
        return optionValue;
    }

    /**
     * 根据单选框的label获取单选框的value值
     *
     * @param resJ
     * @param fieldName
     * @param apiKey
     * @return
     */
    public static Integer getValueByApiKey(JSONObject resJ, String fieldName, String apiKey) {
        if (StringUtils.isBlank(apiKey)) {
            return null;
        }
        Integer optionValue = null;
        Map<String, String> map = getMapsFromDescribeJson(resJ, fieldName, "apiKey", "value");
        for (Map.Entry<String, String> index : map.entrySet()) {
            if (apiKey.equals(index.getKey())) {
                optionValue = Integer.valueOf(index.getValue());
                break;
            }
        }
        return optionValue;
    }

    /**
     * 根据单选框的value(数值) 获取单选框的apiKey值
     *
     * @param resJ
     * @param fieldName
     * @param optionCode
     * @return
     */
    public static String getComboboxApiKey(JSONObject resJ, String fieldName, Integer optionCode) {
        if (optionCode == null) {
            return null;
        }
        Map<String, String> map = getMapsFromDescribeJson(resJ, fieldName, "apiKey", "value");
        for (Map.Entry<String, String> index : map.entrySet()) {
            if (optionCode.toString().equals(index.getValue())) {
                return index.getKey();
            }
        }
        return null;
    }

    /**
     * 根据多选框的value(数值) 获取多选框的label(中文)值
     *
     * @param resJ
     * @param fieldName
     * @param valueList
     * @return
     */
    public static List<String> getComboboxLabelList(JSONObject resJ, String fieldName, Integer[] valueList) {
        List<String> labelList = new ArrayList<>();
        if (valueList == null || valueList.length <= 0) {
            return labelList;
        }
        Map<String, String> map = getMapsFromDescribeJson(resJ, fieldName, true);
        for (Map.Entry<String, String> index : map.entrySet()) {
            for (Integer value : valueList) {
                if (index.getValue().equals(value.toString())) {
                    labelList.add(index.getKey());
                }
            }
        }
        return labelList;
    }


    public static Map<String, String> getMapsFromDescribeJson(JSONObject json, String columnName, String key, String vlaue) {
        Map<String, String> map = new HashMap<>();
        JSONObject dataObj = json.getJSONObject("data");
        JSONArray arrays = dataObj.getJSONArray("fields");
        for (Object index : arrays) {
            JSONObject indexJs = (JSONObject) index;
            if (columnName.equals(indexJs.getString("apiKey"))) {
                JSONArray sels = indexJs.getJSONArray("selectitem");
                for (Object indexSel : sels) {
                    JSONObject selJs = JSONObject.parseObject(indexSel.toString());
                    map.put(selJs.getString(key), selJs.getString(vlaue));
                }
            }
        }
        return map;
    }

    /**
     * @param json
     * @param columnName
     * @param isMultiSelect 是否多选
     * @return
     */
    public static Map<String, String> getMapsFromDescribeJson(JSONObject json, String columnName, Boolean isMultiSelect) {
        Map<String, String> map = new HashMap<>();
        JSONObject dataObj = json.getJSONObject("data");
        JSONArray arrays = dataObj.getJSONArray("fields");
        for (Object index : arrays) {
            JSONObject indexJs = (JSONObject) index;
            if (columnName.equals(indexJs.getString("apiKey"))) {
                JSONArray sels = isMultiSelect ? indexJs.getJSONArray("checkitem") : indexJs.getJSONArray("selectitem");
                for (Object indexSel : sels) {
                    JSONObject selJs = JSONObject.parseObject(indexSel.toString());
                    map.put(selJs.getString("label"), selJs.getString("value"));
                }
            }
        }
        return map;
    }


    /**
     * 根据中文获取多选数值
     *
     * @param multiSelectMap
     * @param propoDemand
     * @return
     */
    private Integer[] getMultiValue(Map<String, String> multiSelectMap, String propoDemand) {
        List<Integer> multiValueList = new ArrayList<>();
        if (StringUtils.isBlank(propoDemand)) {
            return null;
        }
        String[] split = propoDemand.split(",");
        for (String label : split) {
            multiSelectMap.forEach((k, v) -> {
                if (label.equals(v)) {
                    multiValueList.add(Integer.valueOf(k));
                }
            });
        }
        Integer[] multiValueArr = multiValueList.toArray(new Integer[multiValueList.size()]);
        return multiValueArr;
    }


    /*功能描述：获取指定通用选项集的信息
     * 参数globalPickApiKey：通用选项集apiKey
     * 返回值：通用选项集内容
     */
    public static JSONArray getGlobalPicks(String globalPickApiKey) throws IOException {
        RkhdHttpData data = new RkhdHttpData();
        data.setCall_type("GET");
        data.setCallString("/rest/metadata/v2.0/settings/globalPicks/" + globalPickApiKey);
        String response = RkhdHttpClient.instance().performRequest(data);
        logger.debug("获取指定通用选项集的信息：" + response);
        JSONObject json = JSONObject.parseObject(response);
        Integer code = json.getInteger("code");
        if (code == null || code != 0) {
            logger.info("获取通用选项集失败");
            return new JSONArray();
        }
        JSONArray resultArray = json.getJSONObject("data").getJSONObject("records").getJSONArray("pickOption");
        return resultArray;
    }

    /*功能描述：添加通用选项集内容
     * 参数globalPickApiKey：通用选项集apiKey
     * 返回值：通用选项集内容
     */
    public static boolean addGlobalPicks(String globalPickApiKey,JSONObject dataJson) throws IOException {
        RkhdHttpData data = new RkhdHttpData();
        data.setCall_type("POST");
        data.setCallString("/rest/metadata/v2.0/settings/globalPicks/" + globalPickApiKey+"/option");
        JSONObject dataBody = new JSONObject();
        dataBody.put("data", dataJson);
        data.setBody(dataJson.toString());
        String response = RkhdHttpClient.instance().performRequest(data);
        logger.debug("添加通用选项集内容：" + response);
        JSONObject json = JSONObject.parseObject(response);
        Integer code = json.getInteger("code");
        if (code == null || code != 0) {
            logger.info("添加通用选项集内容失败");
            return false;
        }
        logger.debug(json.toJSONString());
        return true;
    }

    /**
     * 获取通用选项集单选
     *
     * @param provinceArray 指定 API 通用选项集
     * @param Label         通用选项集 中文
     * @return
     */
    public static Integer getGeneralValue(JSONArray provinceArray, String Label) {
        if (StringUtils.isBlank(Label)) {
            return null;
        }
        for (Object o : provinceArray) {
            JSONObject faultJson = (JSONObject) o;
            if (Label.equals(faultJson.getString("optionLabel"))) {
                return faultJson.getInteger("optionCode");
            }
        }
        return null;

    }

    /**
     * 获取通用选项集单选
     *
     * @param provinceArray 指定 API 通用选项集
     * @param apiKey        通用选项集编码
     * @return
     */
    public static Integer getValueByApiKey(JSONArray provinceArray, String apiKey) {
        if (StringUtils.isBlank(apiKey)) {
            return null;
        }
        for (Object o : provinceArray) {
            JSONObject faultJson = (JSONObject) o;
            if (apiKey.equals(faultJson.getString("optionApiKey"))) {
                return faultJson.getInteger("optionCode");
            }
        }
        return null;

    }

    /**
     * 获取通用选项集单选,根据optionCode获取optionApiKey
     *
     * @param provinceArray 指定 API 通用选项集
     * @param value         数值
     * @return optionApiKey
     */
    public static String getOptionApiKey(JSONArray provinceArray, Integer value) {
        if (value == null) {
            return null;
        }
        for (Object o : provinceArray) {
            JSONObject faultJson = (JSONObject) o;
            if (value.equals(faultJson.getInteger("optionCode"))) {
                return faultJson.getString("optionApiKey");
            }
        }
        return null;
    }

    /**
     * 获取通用选项集单选,根据optionCode获取optionLabel
     *
     * @param provinceArray 指定 API 通用选项集
     * @param value         数值
     * @return optionApiKey
     */
    public static String getOptionOptionLabel(JSONArray provinceArray, Integer value) {
        if (value == null) {
            return null;
        }
        for (Object o : provinceArray) {
            JSONObject faultJson = (JSONObject) o;
            if (value.equals(faultJson.getInteger("optionCode"))) {
                return faultJson.getString("optionLabel");
            }
        }
        return null;
    }

    /**
     * 获取通用选项集单选,根据optionLabel获取optionApiKey
     *
     * @param provinceArray 指定 API 通用选项集
     * @param label         中文
     * @return optionApiKey
     */
    public static String getOptionApiKey(JSONArray provinceArray, String label) {
        if (label == null) {
            return null;
        }
        for (Object o : provinceArray) {
            JSONObject faultJson = (JSONObject) o;
            if (label.equals(faultJson.getString("optionLabel"))) {
                return faultJson.getString("optionApiKey");
            }
        }
        return null;
    }

    /**
     * 查询某条数据所有成员
     *
     * @param xObjectApiKey 实体apiKey
     * @param recordId      实体数据ID
     * @return
     */
    public static JSONObject queryTeamMemberList(String xObjectApiKey, Long recordId) throws IOException, XsyHttpException {
        RkhdHttpClient instance = RkhdHttpClient.instance();
        RkhdHttpData get = RkhdHttpData.newBuilder().callType("GET").callString("/rest/data/v2.0/xobjects/teamMember/actions/list?xObjectApiKey=" + xObjectApiKey + "&recordId=" + recordId + "&status=all").build();
        JSONObject execute = instance.execute(get, JSONObject::parseObject);
        logger.info("查询结果：" + execute);
        return execute;
    }

    /**
     * 给某实体数据添加团队成员
     *
     * @param userId       数据类型：String 添加团队成员用户id
     * @param recordFromId 表单类型id
     * @param businessId   数据类型：String 数据id
     * @param isUpdate     数据额类型：boolean true：有编辑权限，false：无编辑权限。
     */

    public static boolean addTeamMember(Long userId, Long recordFromId, Long businessId, boolean isUpdate) throws IOException, XsyHttpException {
        RkhdHttpClient rkhdHttpClient = RkhdHttpClient.instance();
        int flag = isUpdate ? 1 : 2;
        RkhdHttpData data = new RkhdHttpData();
        data.setCall_type("POST");
        data.setCallString("/rest/data/v2.0/xobjects/teamMember");
        JSONObject params = new JSONObject();
        JSONObject dataBody = new JSONObject();
        params.put("userId", userId);
        params.put("recordFrom", recordFromId);
        params.put("recordFrom_data", businessId);
        params.put("ownerFlag", flag);
        dataBody.put("data", params);
        data.setBody(dataBody.toString());
        logger.info("添加团队成员请求:【" + data.toString() + "】");
        JSONObject response = rkhdHttpClient.execute(data, JSONObject::parseObject);
        logger.info("添加团队成员结果：【" + response + "】");
        Integer code = response.getInteger("code");
        if (code == null || code != 200) {
            logger.info("添加团队成员失败！");
            return false;
        }
        return true;
    }


    /**
     * @param xObjectApiKey 对象映射规则源主对象实体apikey
     * @param ruleId        对象映射规则ID
     * @param dataId        来源实体数据ID
     */
    public static JSONArray doMappingRule(String xObjectApiKey, Long ruleId, Long dataId) throws IOException, XsyHttpException {
        RkhdHttpData data = new RkhdHttpData();
        data.setCall_type("POST");
        String url = "rest/data/v2.0/xobjects/" + xObjectApiKey + "/actions/createObjectByMapRule?ruleId=" + ruleId + "&dataId=" + dataId;
        data.setCallString(url);
        JSONObject result = RkhdHttpClient.instance().execute(data, JSONObject::parseObject);
        logger.info("调用对象映射规则返回结果:" + result.toJSONString());
        Integer code = result.getInteger("code");
        if (code == null || code != 200) {
            return null;
        }
        JSONArray batchDataArr = result.getJSONArray("batchData");
        return batchDataArr;
    }


    /**
     * @param ids
     * @param targetHighSeaId
     * @throws IOException
     * @throws XsyHttpException
     */
    public static void territoryChange(List<Long> ids, String targetHighSeaId) throws IOException, XsyHttpException {
        RkhdHttpClient instance = RkhdHttpClient.instance();
        JSONObject request = new JSONObject();
        request.put("ids", ids);
        request.put("targetHighSeaId", targetHighSeaId);
        request.put("objectApiKey", "account");
        RkhdHttpData data = new RkhdHttpData();
        data.setCallString("/rest/data/v2.0/xobjects/territory/actions/change");
        data.setCall_type("PUT");
        data.setBody(request.toJSONString());
        String execute = instance.execute(data, e -> e);
        logger.info("修改客户公海池分组结果：" + execute);
    }


    /**
     * 发送通知
     *
     * @param jsonObject
     * @return
     * @throws XsyHttpException
     * @throws IOException
     */
    public static boolean sendNotification(JSONObject jsonObject) throws XsyHttpException, IOException {
        logger.info("通知消息数据：" + jsonObject.toJSONString());
        RkhdHttpClient instance = RkhdHttpClient.instance();
        RkhdHttpData data = new RkhdHttpData();
        data.setCallString("/rest/notice/v2.0/newNotice");
        data.setCall_type("POST");
        data.putHeader("Content-Type", "application/json");
        data.setBody(JSONObject.toJSONString(jsonObject));
        String response = instance.performRequest(data);
        JSONObject responseJson = JSONObject.parseObject(response);
        logger.info("发送通知消息结果：" + responseJson.toJSONString());
        Integer code = responseJson.getInteger("code");
        if (code == null || 200 != code) {
            logger.info("发送通知消息失败");
            return false;
        }
        logger.info("发送通知消息成功：" + response);
        return true;
    }

    /**
     * 构造通知消息报文
     *
     * @param
     * @param
     * @return
     */
    private static JSONObject buildNoticeInfo(String content, Long id, Long userId, Long belongId, String label) {
        JSONObject noticeInfo = new JSONObject();
        noticeInfo.put("noticeType", 0); // 通知类型：0 系统通知
        noticeInfo.put("content", content);

        // 提醒内容
        JSONArray jsonArray = new JSONArray();
        JSONObject mergeField = new JSONObject();
        mergeField.put("customLink", "/final/customize.action?belongId=" + belongId + "&id=" + id);
        mergeField.put("label", label);
        mergeField.put("type", 2);
        jsonArray.add(mergeField);
        noticeInfo.put("mergeFields", jsonArray);
        noticeInfo.put("objectId", id); // 关联对象itemId

        // 通知人
        jsonArray = new JSONArray();
        JSONObject receivers = new JSONObject();
        receivers.put("id", userId);
        receivers.put("receiverType", 0); // 接收消息的类型（0人，1部门，2群组）类型
        jsonArray.add(receivers);
        noticeInfo.put("receivers", jsonArray);
        return noticeInfo;
    }


    /**
     * 根据业务类型ID查询业务类型apikey
     *
     * @param apiKey
     * @param entityType
     * @return
     * @throws IOException
     * @throws XsyHttpException
     */
    public static String getEntityApiKey(String apiKey, Long entityType) throws IOException, XsyHttpException {
        RkhdHttpClient instance = RkhdHttpClient.instance();
        RkhdHttpData get = RkhdHttpData.newBuilder().callType("GET").callString("/rest/data/v2.0/xobjects/" + apiKey + "/busiType").build();
        JSONObject execute = instance.execute(get, JSONObject::parseObject);
        System.err.println(execute.toJSONString());
        Integer code = execute.getInteger("code");
        if (code == null || code != 200) {
            return null;
        }
        JSONObject data = execute.getJSONObject("data");
        JSONArray records = data.getJSONArray("records");
        for (Object record : records) {
            JSONObject json = (JSONObject) record;
            Long id = json.getLong("id");
            if (id.equals(entityType)) {
                String entityApiKey = json.getString("apiKey");
                return entityApiKey;
            }
        }
        return null;
    }

    public static JSONArray getStageListByEntityTypeApiKey(String entityApiKey) throws IOException, XsyHttpException, ScriptBusinessException {
        RkhdHttpClient instance = RkhdHttpClient.instance();
        RkhdHttpData get = RkhdHttpData.newBuilder()
                .callType("POST")
                .callString("/rest/data/v2.0/xobjects/stage/actions/getStageListByEntityTypeApiKey")
                .body("{\"data\":{\"entityTypeApiKey\":\"" + entityApiKey + "\"}}")
                .build();
        System.out.println(get.getBody());
        JSONObject execute = instance.execute(get, JSONObject::parseObject);
        System.err.println(execute.toJSONString());
        Integer code = execute.getInteger("code");
        if (code == 0 || code != 200) {
            throw new ScriptBusinessException("查询销售阶段失败。");
        }
        return execute.getJSONArray("data");
    }


    /**
     * 拆分集合
     *
     * @param <T>           泛型对象
     * @param resList       需要拆分的集合
     * @param subListLength 每个子集合的元素个数
     * @return 返回拆分后的各个集合组成的列表
     * 代码里面用到了guava和common的结合工具类
     **/
    public static <T> List<List<T>> split(List<T> resList, int subListLength) {
        if (resList.size() <= 0 || subListLength <= 0) {
            return new ArrayList<>();
        }
        List<List<T>> ret = new ArrayList<>();
        int size = resList.size();
        if (size <= subListLength) {
            // 数据量不足 subListLength 指定的大小
            ret.add(resList);
        } else {
            int pre = size / subListLength;
            int last = size % subListLength;
            // 前面pre个集合，每个大小都是 subListLength 个元素
            for (int i = 0; i < pre; i++) {
                List<T> itemList = new ArrayList<>();
                for (int j = 0; j < subListLength; j++) {
                    itemList.add(resList.get(i * subListLength + j));
                }
                ret.add(itemList);
            }
            // last的进行处理
            if (last > 0) {
                List<T> itemList = new ArrayList<>();
                for (int i = 0; i < last; i++) {
                    itemList.add(resList.get(pre * subListLength + i));
                }
                ret.add(itemList);
            }
        }
        return ret;
    }

    /*功能描述：批量更新
     * 参数ApiKey：通用选项集apiKey
     * 返回值：更新参数
     */
    public static boolean patchUpdate(String apiKey,JSONObject patchJsonData) throws IOException {
        RkhdHttpData data = new RkhdHttpData();
        data.setCall_type("PATCH");
        data.setCallString("/rest/data/v2.0/xobjects/" + apiKey+"/batch");
        data.setBody(patchJsonData.toString());
        String response = RkhdHttpClient.instance().performRequest(data);
        logger.debug("更新结果：" + response);
        JSONObject json = JSONObject.parseObject(response);
        Integer code = json.getInteger("code");
        if (code == null || code != 200) {
            logger.info("更新单据失败");
            return false;
        }
        logger.debug(json.toJSONString());
        return true;
    }


    /** 批量作废市场活动申请
     *
     */
    public static boolean patchCancelCampaign(String ids) throws IOException, XsyHttpException {
        RkhdHttpData data = new RkhdHttpData();
        data.setCall_type("POST");
        String url = "/rest/data/v2.0/scripts/api/xsy/campaign/patchCancelCampaign?ids=" + ids;
        data.setCallString(url);
        JSONObject result = RkhdHttpClient.instance().execute(data, JSONObject::parseObject);
        logger.info("批量作废结果:" + result.toJSONString());
        Integer code = result.getInteger("code");
        if (code == null || code != 0) {
            logger.info("批量作废失败");
            return false;
        }
        logger.debug(result.toJSONString());
        return true;
    }

    /** 查询用户已授权的license
     */
    public static JSONObject getAssignLicenses(Long userId) throws IOException, XsyHttpException {
        RkhdHttpData data = new RkhdHttpData();
        data.setCall_type("GET");
        String url = "/rest/data/v2.0/xobjects/user/"+userId+"/actions/assignLicenses";
        data.setCallString(url);
        JSONObject result = RkhdHttpClient.instance().execute(data, JSONObject::parseObject);
        logger.info("授权信息:" + result.toJSONString());
       return result;
    }

    /** 用户取消license
     */
    public static Boolean delLicenseAssignments(Long userId,Long licenseID) throws IOException, XsyHttpException {
        RkhdHttpData data = new RkhdHttpData();
        data.setCall_type("DELETE");
        String url = "/rest/data/v2.0/xobjects/user/"+userId+"/licenseAssignments/"+licenseID;
        data.setCallString(url);
        JSONObject result = RkhdHttpClient.instance().execute(data, JSONObject::parseObject);
        logger.info("取消授权结果:" + result.toJSONString());
        Integer code = result.getInteger("code");
        if (code == null || code != 0) {
            logger.info("取消授权结果");
            return false;
        }
        logger.debug(result.toJSONString());
        return true;
    }


    //发送通知 ( 支持新消息体结构 )
    public static boolean sendNotice(JSONObject param) throws IOException {
        RkhdHttpData data = new RkhdHttpData();
        data.setCall_type("POST");
        data.setCallString("/rest/notice/v2.0/newNotice");
        data.setBody(param.toString());
        String response = RkhdHttpClient.instance().performRequest(data);
        logger.debug("发送结果：" + response);
        JSONObject json = JSONObject.parseObject(response);
        Integer code = json.getInteger("code");
        if (code == null || code != 200) {
            logger.info("发送通知失败");
            return false;
        }
        logger.debug(json.toJSONString());
        return true;
    }
}
